package com.gaoxk.interceptor;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.springframework.stereotype.Component;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;
import java.util.List;

/**
 * 权限验证拦截器：检查请求头中的Token
 * 入站拦截器（处理客户端请求）
 * plaintext
 * RECEIVE → READ → POST_READ → PRE_PROTOCOL → PROTOCOL → POST_PROTOCOL →
 * UNMARSHAL → POST_UNMARSHAL → PRE_INVOKE → INVOKE → POST_INVOKE
 * 出站拦截器（处理服务端响应）
 * plaintext
 * SETUP → PRE_LOGICAL → LOGICAL → POST_LOGICAL → PRE_MARSHAL → MARSHAL →
 * POST_MARSHAL → PRE_PROTOCOL → PROTOCOL → POST_PROTOCOL → PREPARE_SEND → SEND
 *
 * RECEIVE：刚接收到原始请求数据（最早阶段）。
 * UNMARSHAL：将 XML 报文解析为 Java 对象（反序列化）。
 * PRE_INVOKE：调用业务方法前（适合权限校验、状态检查等）。
 * INVOKE：执行服务实现类的业务方法。
 * MARSHAL：将 Java 对象转换为 XML 报文（序列化）。
 * SEND：发送响应数据（最后阶段）。
 * 优先使用阶段划分：不同阶段的拦截器执行顺序是固定的，这是最可靠的优先级控制方式。例如：
 * 数据校验、权限检查→PRE_INVOKE
 * 业务逻辑→INVOKE
 * 响应加工→POST_INVOKE
 * 同阶段用 order 微调：同一阶段内的拦截器（如多个日志拦截器），用order控制执行顺序。
 * 复杂依赖用 addBefore/addAfter：当拦截器存在强依赖关系（如解密必须在验签前），使用相对位置控制。
 * 避免过度使用低阶段：RECEIVE、READ等早期阶段仅适合处理原始字节流，不适合业务逻辑（此时 XML 尚未解析）。
 */
@Component
public class AuthInterceptor extends AbstractSoapInterceptor {

    // 指定在"调用业务方法前"阶段执行
    public AuthInterceptor() {
        super(Phase.PRE_INVOKE);
        //通过addAfter/addBefore指定拦截器的相对位置，强制某个拦截器在另一个拦截器之前 / 之后执行（无视 order）。
        //ddAfter(LoggingInInterceptor.class.getName());
        //同一阶段内的多个拦截器，通过setOrder(int)设置优先级，值越小越先执行（默认 0）。
        //this.setOrder(0);
    }

    @Override
    public void handleMessage(SoapMessage message) throws Fault {
        try {
            // 从SOAP头中获取Token
            String token = getTokenFromHeader(message);
            
            // 验证Token（实际应调用认证服务）
//            if (token == null || !"VALID_TOKEN".equals(token)) {
//                // 验证失败，抛出SOAP错误
//                throw new Fault(new Exception("权限验证失败：无效的Token"));
//            }
            System.out.println("权限验证通过");
        } catch (Fault e) {
            throw e; // 直接抛出已包装的SOAP错误
        } catch (Exception e) {
            throw new Fault(new Exception("权限拦截器处理失败", e));
        }
        /*
        SoapFault fault = new SoapFault(
                "账号格式错误，必须为16位数字",
                new QName("http://schemas.xmlsoap.org/soap/envelope/", "Client", "soap")
        );

        // 添加自定义错误详情（会被序列化为XML的<detail>元素）
        AccountErrorDetail detail = new AccountErrorDetail();
        detail.setInvalidField("accountNo");
        detail.setRule("必须为16位数字");
        detail.setReceivedValue(request.getAccountNo());
        fault.setDetail(detail);

        throw fault;

         */
    }

    // 从SOAP Header中提取Token
    private String getTokenFromHeader(SoapMessage message) {
        List<Header> headers = message.getHeaders();
        QName tokenQName = new QName("http://your-company.com/auth", "Token");
        
        for (Header header : headers) {
            if (tokenQName.equals(header.getName())) {
                Element tokenElement = (Element) header.getObject();
                return tokenElement.getTextContent();
            }
        }
        return null;
    }
}
